//
//      A Visible View
//      Randy Nelson, NeXT Developer Training
//      Created 5-1-90
//	Modified 9-3-90 for 2.0
//
//	You may freely copy, distribute and reuse the code in this example.
//	NeXT disclaims any warranty of any kind, expressed or implied, as to
//	its fitness for any particular use.
//

#import "VisibleOne.h"
#import "StringManager.h"
#import <appkit/View.h>
#import <appkit/publicWraps.h>
#import <dpsclient/wraps.h>
#import <appkit/graphics.h>
#import <appkit/Application.h>
#import <appkit/Font.h>
#import <appkit/Form.h>
#import <appkit/Control.h>
#import <appkit/Button.h>
#import <appkit/NXImage.h>
#import <objc/NXStringTable.h>
#import <libc.h>
#import "SubViewFramer.h"
#import "Drawgrid.h"
#import "SomePS.h"
#import "Appender.h"

@implementation VisibleOne

//sets clipping off
- initFrame:(const NXRect *)framerect;
{
    [super initFrame:framerect];
    [self setClipping:NO];
    //because we read strings in our drawSelf::
    //we must assure they'll be there by the first time it's called
    stringSet = [[[StringManager alloc] init] stringSet];
    
    //save some defs in the window server
    somedefs();
    
    return self;
}

//translate
- setSelfOrigin:sender
{
    //the slider returns values that are the opposite of what we need
    [self setDrawOrigin:([translateX intValue] *( -1))
	    :([translateY intValue] *( -1))];
    [window display];
    return self;
}

//scale
- setSelfScale:sender
{
    //can't scale by zero
    if ([scaleX floatValue] == 0) {
    	[scaleX setIntValue:1];
    }
    if ([scaleY floatValue] == 0) {
    	[scaleY setIntValue:1];
    }
    [self scale:[scaleX floatValue] :[scaleY floatValue]];
    [window display];

    //reset the interface values
    [scaleX setIntValue:1];
    [scaleY setIntValue:1];
    
    return self;
}

//rotate
- setSelfRotation:sender
{
    [self setDrawRotation:[sender intValue]];
    [window display];
    return self;
}

//move frame
- frameMove:sender
{
    [self moveTo:[frameX intValue] :[frameY intValue]];
    [window display];
    [self setTrackingRect];
    return self;
}

//rotate frame
//tracking rects don't work when your frame is rotated
- frameRotate:sender
{
    [self rotateTo:[sender intValue]];
    [window display];
    return self;
}

//resize frame
- frameChangeSize:sender
{
    [self sizeTo:[frameWidth intValue] :[frameHeight intValue]];
    [self setTrackingRect];
    [window display];
    return self;
}

//sent by the preferences buttons to force a redraw, reflecting their new state
- newDisplayState:sender
{
        [window display];
        return self;
}

//delegate method of app
- appDidInit:sender
{
    NXRect aRect = {0.0, 0.0, 0.0, 0.0};
    
    [appender appendToText:
    [stringSet valueForStringKey:"Received appDidInit:"]];
    
    //gets the image for compositing & scales it to frame
    myPic = [NXImage findImageNamed:[stringSet valueForStringKey:"Logo"]];
    [myPic setScalable:YES];
    [myPic setSize:&frame.size];
    
    //sets up the subViewFramer as our superview
    newSuperView = [SubViewFramer alloc];
    [newSuperView initFrame:&aRect];
    [window setContentView:newSuperView];
    [newSuperView addSubview:self];
    [newSuperView display];
	    
    [self setTrackingRect];
    [window makeKeyAndOrderFront:self];
    return self;
}

//allows us to become first responder
- (BOOL)acceptsFirstResponder
{
    [appender appendToText:
    [stringSet valueForStringKey:
    			  "Received acceptsFirstResponder -- returning YES"]];
    return YES;
}

//allows us to use the mouse click that activates the window
- (BOOL)acceptsFirstMouse
{
    [appender appendToText:
    [stringSet valueForStringKey:
    			     "Received acceptsFirstMouse -- returning YES"]];
    return YES;
}

//draws the view and then calls the superview for framing
- drawSelf:(NXRect *)r :(int)c
{
    NXPoint zero = {0.0, 0.0};
    
    [self updateVitals];
    if([compositeIndicator state]){
	    [myPic composite:NX_SOVER toPoint:&zero];
    }
    if([drawGridIndicator state]){
	    PSselectfont( (char *)NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:"Times-Italic"]), 24.0);
	    PSsetgray(NX_WHITE);
	    RNdrawgrid();
    }
    
    if (NXDrawingStatus != NX_DRAWING) {
        //make sure we send the defs to the printer or pasteboard
        somedefs();
    }
    
    //draws the views basic contents
    somePS();
    
    //displays the bounds rect
    PSsetgray(NX_BLACK);
    sprintf(buffer, NXUniqueStringNoCopy(
    [stringSet valueForStringKey:"bounds.origin.x %.1f,.y %.1f"]),
    bounds.origin.x, bounds.origin.y);
    PSmoveto(bounds.origin.x, (bounds.origin.y - 18));
    PSselectfont((char *)NXUniqueStringNoCopy(
    [stringSet valueForStringKey:"Times-Italic"]), 24.0);
    PSshow(buffer);
    NXFrameRect(&bounds);
    
    //calls the subViewFramer, our superview
    [newSuperView frameMe:self];
    
    return self;
}

//indicates the mouse down with a beep
- mouseDown:(NXEvent *)e
{
    sprintf(buffer, NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:
	    "Received mouseDown: -- window coordinates %.f, %.f"]),
	    e->location.x, e->location.y);  
    [appender appendToText:buffer];
    NXBeep();
    return self;
}

//indicates at the location of the mouse at mouse up using instance drawing
- mouseUp:(NXEvent *)e
{
    NXPoint mousePoint = e->location;

    sprintf(buffer, NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:
	    "Received mouseUp: -- window coordinates %.f, %.f"]),
    	    e->location.x, e->location.y);
    [appender appendToText:buffer];
    [self convertPointFromSuperview:&mousePoint];
    [self lockFocus];
	PSselectfont( (char *) NXUniqueStringNoCopy(
	[stringSet valueForStringKey:"Times-Italic"]), 24.0);
	PSsetgray(NX_DKGRAY);
	PSnewinstance();
	PSsetinstance(YES);
	    PSmoveto(mousePoint.x, mousePoint.y);
	    PSsetgray(0.0);
	    PSrectfill(mousePoint.x-2.0,
	    mousePoint.y-2.0, 4.0, 4.0);
	    PSmoveto(mousePoint.x+4.0, mousePoint.y+4.0);
	    sprintf(buffer, NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:"%.f, %.f"]),
	    mousePoint.x, mousePoint.y);
	    PSshow(buffer);
	PSsetinstance(NO);
    [self unlockFocus];
    return self;
}

//tracks the mouse entering the view
- mouseEntered:(NXEvent *)e
{
    sprintf(buffer, NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:
	    "Received mouseEntered: -- window coordinates %.f, %.f"]),
	    e->location.x, e->location.y);
    [appender appendToText:buffer];
    return self;
}

//tracks the mouse leaving the view
- mouseExited:(NXEvent *)e
{
    sprintf(buffer, NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:
	    "Received mouseExited: -- window coordinates %.f, %.f"]),
	    e->location.x, e->location.y);
    [appender appendToText:buffer];
    return self;
}

//gets keyUps
- keyUp:(NXEvent *)e
{
    [appender appendToText:[stringSet valueForStringKey:"Received keyUp:"]];
    return self;
}

//gets keyDowns
- keyDown:(NXEvent *)e
{
    sprintf(buffer, NXUniqueStringNoCopy(
	    [stringSet valueForStringKey:"Received keyDown: -- char '%c'"]),
	    e->data.key.charCode);
    [appender appendToText:buffer];
    return self;
}

//checks to see if the mouse down was in this view
- hitTest:(NXPoint *)aPt
{
    [appender appendToText:
			[stringSet valueForStringKey:"Received hitTest:"]];
    if ([super hitTest:aPt]){
	[appender appendToText:
		[stringSet valueForStringKey:" -- YES inside this view"]];
	return self;
    }
    [appender appendToText:
		[stringSet valueForStringKey:" -- NO not inside this view"]];
    return  nil;
}

//updates the statistics matrix
- updateVitals
{
    [[[[[[[[[[vitalMatrix setFloatValue:bounds.origin.x at:0]
	setFloatValue:bounds.origin.y at:1]
	setFloatValue:bounds.size.width at:2]
	setFloatValue:bounds.size.height at:3]
	setFloatValue:[self boundsAngle] at:4]
	setFloatValue:frame.origin.x at:5]
	setFloatValue:frame.origin.y at:6]
	setFloatValue:frame.size.width at:7]
	setFloatValue:frame.size.height at:8]
	setFloatValue:[self frameAngle] at:9];
    return self;
}

//for communication with the transparent superview
- (BOOL)wantsTransparency
{
    return [transparencyIndicator state];
}

- setTrackingRect
{
    NXRect aRect;
    
    //registers the tracking rect
    aRect = frame;
    [superview convertRect:&aRect toView:nil];
    [appender appendToText:
	[stringSet valueForStringKey:"Sending setTrackingRect:... to window"]];
    [window setTrackingRect:&aRect
	    inside:NO
	    owner:self
	    tag:23
	    left:NO
	    right:NO];
    return self;
}

- infoPanel:sender
{
    if(infoPanel == nil){
	[NXApp loadNibSection:"Info.nib" owner:self];
    }
    [infoPanel orderFront:sender];
    return self;
}

@end
